﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Clmp.Web
{
    public class HtmlHelper
    {
        static char END_SLASH = '/';
        /// <summary>
        /// 安全的截断字符串
        /// </summary>
        /// <param name="input">输入串</param>
        /// <param name="length">截断长度</param>
        /// <param name="trimHalfTag">true：截断半截标签；false：补全半截标签</param>
        /// <param name="tagStartChar">标签开始字符</param>
        /// <param name="tagEndChar">标签结束字符</param>
        /// <param name="mustCloseTags">需要关闭的标签数组</param>
        /// <returns>length长度的字符串</returns>
        public static string SafeTrim(string input, int length, bool trimHalfTag, char tagStartChar, char tagEndChar, string[] mustCloseTags)
        {
            if (length <= 0) throw new ArgumentException("length 必须是正数");
            if (mustCloseTags == null) throw new ArgumentNullException("mustCloseTags");

            int inputLen = input.Length;
            if (string.IsNullOrEmpty(input) || inputLen <= length) return input;

            string result = string.Empty;

            //声明堆栈用来放标签
            Stack<string> tags = new Stack<string>();

            for (int i = 0; i < length; i++)
            {
                char c = input[i];

                if (c == tagStartChar)
                {
                    string tag = string.Empty;
                    int tagIndex = i + 1;
                    bool isTagEnd = false;
                    bool isTagNameEnd = false;
                    result += c;
                    bool hasMarkTagInStack = false;
                    while (tagIndex < inputLen)
                    {
                        char tagC = input[tagIndex];
                        result += tagC;
                        tagIndex++;
                        if (tag == string.Empty && tagC == END_SLASH)
                        {
                            isTagEnd = true;
                            continue;
                        }
                        if (!isTagNameEnd)
                        {
                            if (char.IsLetter(tagC) || char.IsNumber(tagC))
                            {
                                tag += tagC;
                            }
                            else
                            {
                                isTagNameEnd = true;
                            }
                        }

                        if (!string.IsNullOrEmpty(tag))
                        {
                            if (isTagNameEnd && !hasMarkTagInStack)
                            {
                                if (isTagEnd)
                                {
                                    tags.Pop();
                                }
                                else
                                {
                                    tags.Push(tag);
                                }
                                hasMarkTagInStack = true;
                            }
                        }

                        if (isTagNameEnd)
                        {
                            if (tagC == tagEndChar)
                            {
                                i = tagIndex - 1;
                                break;
                            }
                        }

                    }
                }
                else
                {
                    result += c;
                }
            }

            while (tags.Count > 0)
            {
                string tag = tags.Pop();

                bool isMustCloseTag = false;
                foreach (string mustCloseTag in mustCloseTags)
                {
                    if (string.Compare(mustCloseTag, tag, true) == 0)
                    {
                        isMustCloseTag = true;
                        break;
                    }
                }
                if (isMustCloseTag)
                {
                    if (trimHalfTag)
                    {
                        int lastTagIndex = result.LastIndexOf(tagStartChar.ToString() + tag, StringComparison.CurrentCultureIgnoreCase);

                        result = result.Substring(0, lastTagIndex);
                    }
                    else
                    {
                        result += (tagStartChar.ToString() + END_SLASH + tag + tagEndChar);
                    }
                }
            }

            return result;
        }
    }
}
